package work.mediway.mdm.biz.service.biz.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mediway.hos.app.base.seure.util.SecurityUtils;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import work.mediway.mdm.core.enums.StatusWhetherEnum;
import work.mediway.mdm.core.util.DUtil;
import work.mediway.mdm.biz.dto.biz.SsFieldPermDTO;
import work.mediway.mdm.biz.mapper.biz.SsUserLinkFieldMapper;
import work.mediway.mdm.biz.service.biz.SsRoleLinkFieldService;
import work.mediway.mdm.biz.vo.biz.SsFieldPermVO;
import work.mediway.mdm.biz.entity.biz.SsRoleLinkField;
import work.mediway.mdm.biz.entity.biz.SsUserLinkField;
import work.mediway.mdm.biz.helper.BusinessDatabaseHelper;
import work.mediway.mdm.biz.service.biz.SsUserLinkFieldService;
import work.mediway.mdm.biz.vo.dict.DictFieldVO;

/**
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2021/3/25
 */
@Service
public class SsUserLinkFieldServiceImpl extends ServiceImpl<SsUserLinkFieldMapper, SsUserLinkField> implements SsUserLinkFieldService {

    @Resource
    private BusinessDatabaseHelper businessDatabaseHelper;
    @Resource
    private SsRoleLinkFieldService roleLinkFieldService;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveFieldPerm(List<SsUserLinkField> userLinkFields) {
        List<SsRoleLinkField> updateTableRoleData = CollUtil.newArrayList();
        List<SsUserLinkField> updateTableUserData = CollUtil.newArrayList();
        List<SsRoleLinkField> saveTableRoleData = CollUtil.newArrayList();
        List<SsUserLinkField> saveTableUserData = CollUtil.newArrayList();
        List<SsUserLinkField> notExistData = CollUtil.newArrayList();

        List<SsUserLinkField> containLinkId = userLinkFields.stream().filter(item -> ObjectUtil.isNotEmpty(item.getSsLinkId())).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(containLinkId)) {
            List<Long> linkIds = containLinkId.stream().map(SsUserLinkField::getSsLinkId).collect(Collectors.toList());
            List<SsRoleLinkField> ssRoleLinkFields = this.roleLinkFieldService.listByIds(linkIds);
            Map<Long, SsRoleLinkField> roleLinkFieldMap = ssRoleLinkFields.stream().collect(Collectors.toMap(SsRoleLinkField::getSsLinkId, ssRoleLinkField -> ssRoleLinkField));
            List<SsUserLinkField> ssUserLinkFields = this.listByIds(linkIds);
            Map<Long, SsUserLinkField> userLinkFieldMap = ssUserLinkFields.stream().collect(Collectors.toMap(SsUserLinkField::getSsLinkId, userLinkField -> userLinkField));
            userLinkFields.forEach(item -> {
                if (ObjectUtil.isNotEmpty(roleLinkFieldMap.get(item.getSsLinkId()))) {
                    SsRoleLinkField ssRoleLinkTable = roleLinkFieldMap.get(item.getSsLinkId());
                    BeanUtil.copyProperties(item, ssRoleLinkTable);
                    ssRoleLinkTable.setSsUpdateDate(DUtil.splitNow()[0]);
                    ssRoleLinkTable.setSsUpdateTime(DUtil.splitNow()[1]);
                    ssRoleLinkTable.setSsUpdateUser(SecurityUtils.getLoginName());
                    ssRoleLinkTable.setSsOrder(item.getSsOrder());
                    updateTableRoleData.add(ssRoleLinkTable);
                } else if (ObjectUtil.isNotEmpty(userLinkFieldMap.get(item.getSsLinkId()))) {
                    SsUserLinkField ssUserLinkTable = userLinkFieldMap.get(item.getSsLinkId());
                    BeanUtil.copyProperties(item, ssUserLinkTable);
                    ssUserLinkTable.setSsUpdateDate(DUtil.splitNow()[0]);
                    ssUserLinkTable.setSsUpdateTime(DUtil.splitNow()[1]);
                    ssUserLinkTable.setSsUpdateUser(SecurityUtils.getLoginName());
                    ssUserLinkTable.setSsOrder(item.getSsOrder());
                    updateTableUserData.add(ssUserLinkTable);
                } else {
                    notExistData.add(item);
                }
            });
            savePrem(updateTableRoleData, updateTableUserData, saveTableRoleData, saveTableUserData, notExistData);
        } else {
            savePrem(updateTableRoleData, updateTableUserData, saveTableRoleData, saveTableUserData, userLinkFields);
        }
    }

    private void savePrem(List<SsRoleLinkField> updateTableRoleData, List<SsUserLinkField> updateTableUserData, List<SsRoleLinkField> saveTableRoleData, List<SsUserLinkField> saveTableUserData, List<SsUserLinkField> notExistData) {
        notExistData.forEach(item -> {
            item.setSsCreateDate(DUtil.splitNow()[0]);
            item.setSsCreateTime(DUtil.splitNow()[1]);
            item.setSsCreateUser(SecurityUtils.getLoginName());
            item.setSsUpdateDate(DUtil.splitNow()[0]);
            item.setSsUpdateTime(DUtil.splitNow()[1]);
            item.setSsUpdateUser(SecurityUtils.getLoginName());
            if (StrUtil.isNotBlank(item.getSsRole())) {
                // 绑定角色
                SsRoleLinkField roleLinkField = BeanUtil.copyProperties(item, SsRoleLinkField.class);
                roleLinkField.setSsRole(item.getSsRole());
                saveTableRoleData.add(roleLinkField);
            }
            if (StrUtil.isNotBlank(item.getSsUser())) {
                // 绑定用户
                saveTableUserData.add(item);
            }
        });
        this.roleLinkFieldService.updateBatchById(updateTableRoleData);
        this.updateBatchById(updateTableUserData);
        this.roleLinkFieldService.saveOrUpdateBatch(saveTableRoleData);
        this.saveOrUpdateBatch(saveTableUserData);
    }

    @Override
    public List<SsFieldPermVO> listFieldPerm(SsFieldPermDTO fieldPermDTO) {
        // 解决XML中动态SQL为空
        if (StrUtil.isAllBlank(fieldPermDTO.getUserId(), fieldPermDTO.getRoleId(), fieldPermDTO.getExtraSystemCode())) {
            fieldPermDTO.setUserId("-1");
        }
        List<SsFieldPermVO> result = CollUtil.newArrayList();
        List<String> tmp = CollUtil.newArrayList();
        List<DictFieldVO> column = this.businessDatabaseHelper.getColumn(fieldPermDTO.getSsTableParam());
        Map<String, String> columnMap = column.stream()
                .distinct()
                .filter(item -> StrUtil.isNotBlank(item.getFieldCode()))
                .collect(Collectors.toMap(DictFieldVO::getFieldCode, DictFieldVO::getFieldDesc));
        List<SsFieldPermVO> fieldPerm = this.baseMapper.listFieldPerm(fieldPermDTO);

        // 先放置有权限标识的字段
        for (int i = 0; i < fieldPerm.size(); i++) {
            fieldPerm.get(i).setSsFieldDesc(columnMap.get(fieldPerm.get(i).getSsField()));
            fieldPerm.get(i).setRowId(String.valueOf(i + 1));
            fieldPerm.get(i).setSsRole(fieldPermDTO.getRoleId());
            fieldPerm.get(i).setSsUser(fieldPermDTO.getUserId());
            fieldPerm.get(i).setSsTable(fieldPermDTO.getSsTableParam());
            result.add(fieldPerm.get(i));
            tmp.add(fieldPerm.get(i).getSsField());
        }

        // 再拼接没有绑定权限标识的字段
        for (int i = 0; i < column.size(); i++) {
            if (!CollUtil.contains(tmp, column.get(i).getFieldCode())) {
                SsFieldPermVO vo = new SsFieldPermVO();
                vo.setSsField(column.get(i).getFieldCode());
                vo.setSsFieldDesc(column.get(i).getFieldDesc());
                if (StrUtil.isBlank(SecurityUtils.getSingleUserRoleId())) {
                    vo.setSsBrowse(StatusWhetherEnum.STATUS_Y.getStatusCode());
                    vo.setSsEdit(StatusWhetherEnum.STATUS_Y.getStatusCode());
                } else {
                    vo.setSsBrowse(StatusWhetherEnum.STATUS_N.getStatusCode());
                    vo.setSsEdit(StatusWhetherEnum.STATUS_N.getStatusCode());
                }
                vo.setRowId(String.valueOf((i + tmp.size() + 1)));
                vo.setSsRole(fieldPermDTO.getRoleId());
                vo.setSsTable(fieldPermDTO.getSsTableParam());
                vo.setSsUser(StrUtil.equals(fieldPermDTO.getUserId(), "-1") ? "" : fieldPermDTO.getUserId());
                result.add(vo);
            }
        }

        // 条件过滤
        if (StrUtil.isNotBlank(fieldPermDTO.getSsFieldParam())) {
            return result.stream()
                    .filter(item -> StrUtil.equalsIgnoreCase(item.getSsField(), fieldPermDTO.getSsFieldParam())
                            || StrUtil.equalsIgnoreCase(item.getSsFieldDesc(), fieldPermDTO.getSsFieldParam()))
                    .collect(Collectors.toList());
        }
        return result;
    }
}
